package com.example.origin.redis.config;

import com.example.origin.redis.utils.SerializerUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.cache.support.CompositeCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.serializer.RedisSerializationContext;

import java.time.Duration;
import java.util.ArrayList;
import java.util.List;

@Slf4j
@EnableCaching
@Configuration
public class RedisCacheConfiguration {
    @Bean
    public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
        ConcurrentMapCacheManager concurrentMapCacheManager = new ConcurrentMapCacheManager();
        concurrentMapCacheManager.setAllowNullValues(false);
        RedisCacheManager redisCacheManager = new RedisCacheManager(
                RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory),
                this.getRedisCacheConfigurationWithTtl(12 * 60 * 60) // 默认策略，未配置的 key 会使用这个
        );
        return new CompositeCacheManager(redisCacheManager);
    }

    private org.springframework.data.redis.cache.RedisCacheConfiguration getRedisCacheConfigurationWithTtl(Integer seconds) {
        org.springframework.data.redis.cache.RedisCacheConfiguration redisCacheConfiguration = org.springframework.data.redis.cache.RedisCacheConfiguration.defaultCacheConfig();
        redisCacheConfiguration = redisCacheConfiguration.serializeValuesWith(
                RedisSerializationContext
                        .SerializationPair
                        .fromSerializer(SerializerUtil.createJackson2JsonRedisSerializer())
        ).entryTtl(Duration.ofSeconds(seconds));
        return redisCacheConfiguration;
    }


    @Bean(name = "wiselyKeyGenerator")
    public KeyGenerator wiselyKeyGenerator() {
        return (target, method, params) -> {
            StringBuilder sb = new StringBuilder();
            sb.append(method.getName());
            if (params.length == 0 || params[0] == null) {
                return sb.toString();
            }
            List<String> list = new ArrayList<>();
            list.add(sb.toString());
            for (Object param : params) {
                list.add(param.toString());
            }
            return String.join(":", list);
        };
    }
}
